package com.alogic.terminal.xscript;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.anysoft.util.*;
import org.apache.commons.lang3.StringUtils;
import org.w3c.dom.Attr;
import org.w3c.dom.Element;
import com.alogic.terminal.Terminal;
import com.alogic.terminal.local.Local;
import com.alogic.terminal.ssh.SSH;
import com.alogic.xscript.ExecuteWatcher;
import com.alogic.xscript.Logiclet;
import com.alogic.xscript.LogicletContext;
import com.alogic.xscript.doc.XsObject;
import com.alogic.xscript.plugins.Segment;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;

/**
 * Shell插件
 * @author duanyy
 * @version 1.6.7.11 [20170203 duanyy] <br>
 * - 指令为空时将忽略，不执行 <br>
 * 
 * @version 1.6.9.9 [20170829 duanyy] <br>
 * - 增加ssh改密码功能 <br>
 *
 * @version 1.6.13.38 [20210224 duanyy] <br>
 * - 增加x-cmd-out指令 <br>
 */
public class XShell extends Segment{

	/**
	 * 属性列表
	 */
	protected List<Pair<String,String>> attrList = new ArrayList<Pair<String,String>>();
	
	/**
	 * 上下文id
	 */
	protected String id = "$xshell";
	
	public XShell(String tag, Logiclet p) {
		super(tag, p);
		registerModule("x-cmd",XCmd.class);
		registerModule("x-change-pwd",XChangePwd.class);
		registerModule("x-cmd-out",XCmdOut.class);
	}

	@Override
	public void configure(Properties p){
		super.configure(p);
		id = PropertiesConstants.getString(p, "id", id ,true);
	}
	
	@Override
	public void configure(Element e, Properties p) {
		super.configure(e, p);

		NamedNodeMap attrs = e.getAttributes();
		for (int i = 0 ;i < attrs.getLength() ; i ++){
			Node n = attrs.item(i);
			if (Node.ATTRIBUTE_NODE != n.getNodeType()){
				continue;
			}
			Attr attr = (Attr)n;

			String key = attr.getName();
			String value = attr.getValue();

			if (StringUtils.isNotEmpty(key) && StringUtils.isNotEmpty(value)){
				attrList.add(new Pair.Default<String,String>(key,value));
			}
		}
	}	

	@Override
	protected void onExecute(XsObject root,XsObject current, LogicletContext ctx, ExecuteWatcher watcher){
		DefaultProperties props = new DefaultProperties("Default",ctx);

		for (Pair<String,String> pair:attrList){
			String key = PropertiesConstants.transform(ctx,pair.key(),"");
			String value = PropertiesConstants.transform(ctx,pair.value(),"");
			if (StringUtils.isNotEmpty(value) && StringUtils.isNotEmpty(value)){
				props.SetValue(key,value);
			}
		}

		Terminal t = null;
		TerminalFactory f = new TerminalFactory();
		String module = PropertiesConstants.getString(props,"module","local",true);
		try{
			t = f.newInstance(module, props);
		}catch (Exception ex){
			log(String.format("Can not create terminal with %s",module));
		}

		if (t != null){
			try{
				t.connect();
				ctx.setObject(id, t);
				super.onExecute(root, current, ctx, watcher);
			}finally{
				ctx.removeObject(id);
				t.disconnect();
			}
		}
	}
	
	/**
	 * 工厂类
	 * @author yyduan
	 *
	 */
	public static class TerminalFactory extends Factory<Terminal>{
		protected static Map<String,String> mapping = new HashMap<String,String>();
		public String getClassName(String module){
			String found = mapping.get(module);
			return StringUtils.isEmpty(found)?module:found;
		}
		
		static{
			mapping.put("local", Local.class.getName());
			mapping.put("ssh", SSH.class.getName());
		}
	}
}
